package cn.yeziji.forum.dao.iquery;

import cn.org.atool.fluent.mybatis.If;
import cn.org.atool.fluent.mybatis.base.crud.IQuery;
import cn.org.atool.fluent.mybatis.base.crud.JoinBuilder;
import cn.yeziji.forum.dto.question.QuestionPagingDTO;
import cn.yeziji.forum.entity.ForumQuestionAnswerEntity;
import cn.yeziji.forum.entity.ForumQuestionEntity;
import cn.yeziji.forum.entity.ForumUserEntity;
import cn.yeziji.forum.entity.ForumUserQaEntity;
import cn.yeziji.forum.wrapper.ForumQuestionAnswerQuery;
import cn.yeziji.forum.wrapper.ForumQuestionQuery;
import cn.yeziji.forum.wrapper.ForumUserQaQuery;
import cn.yeziji.forum.wrapper.ForumUserQuery;

/**
 * 问题 query
 *
 * @author gzkemays
 * @since 2022/11/12 5:45 PM
 */
public class QuestionQuery {
  /**
   * 获取用户7天内的问题
   *
   * @param userId 用户 ID
   */
  public static IQuery getUser7DaysQuestionsQuery(Integer userId) {
    return new ForumQuestionQuery("fq")
        .selectAll()
        .where
        .userId()
        .eq(userId)
        .and(
            q ->
                q.where
                    .applyFunc(
                        "DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(fq.createTime) or DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(fq.updateTime)")
                    .end())
        .end();
  }

  /**
   * 模糊查询标题或内容匹配的数据
   *
   * <pre lang="sql">
   * SELECT
   *  fq.title,
   *  fq.content,
   *  fq.collectionNumber,
   *  fq.createTime,
   *  fq.updateTime,
   *  fu.nickname,
   *  fuq.toOpera,
   *  count( fqa.questionId ) AS answerNumber
   * FROM
   * forum_question fq
   *  LEFT JOIN forum_user fu ON fq.userId = fu.id
   *  LEFT JOIN forum_question_answer fqa ON fq.id = fqa.questionId
   *  LEFT JOIN forum_user_qa fuq ON fuq.questionId = fq.id
   *  AND ( fuq.`userId` = 19 OR fuq.`userId` IS NULL )
   * WHERE
   *  fq.`delete` = 0
   *  AND (
   *  fq.title LIKE concat( '%', 'xxx', '%' )
   *  OR fq.content LIKE concat( '%', 'xxx', '%' ))
   *  GROUP BY
   *  fqa.questionId,
   *  fuq.toOpera;
   * </pre>
   *
   * @param dto 模糊查询文本
   * @return 查询条件
   */
  public static IQuery blurTitleOrContentQuery(QuestionPagingDTO dto) {
    String text = dto.getContent();
    Integer userId = dto.getUserId();
    Integer questionId = dto.getQuestionId();
    return JoinBuilder.from(
            new ForumQuestionQuery()
                .select
                .id()
                .title()
                .content()
                .viewNumber()
                .collectionNumber()
                .answerId()
                .createTime()
                .updateTime()
                .end()
                .where
                .delete()
                .isFalse()
                .and
                .id()
                .eq(questionId, If::notNull)
                .and(
                    content ->
                        content
                            .where
                            .title()
                            .like(text, If::notBlank)
                            .or
                            .content()
                            .like(text, If::notBlank)
                            .end())
                .end()
                .groupBy
                .id()
                .end())
        .leftJoin(new ForumUserQuery().select.nickname().end())
        .onEq(ForumQuestionEntity::getUserId, ForumUserEntity::getId)
        .endJoin()
        .leftJoin(
            new ForumQuestionAnswerQuery()
                .select
                .count
                .questionId("answerNumber")
                .end()
                .groupBy
                .questionId()
                .end())
        .onEq(ForumQuestionEntity::getId, ForumQuestionAnswerEntity::getQuestionId)
        .endJoin()
        .leftJoin(new ForumUserQaQuery().select.toOpera().userId().end())
        .onEq(ForumQuestionEntity::getId, ForumUserQaEntity::getQuestionId)
        .onRight(
            query ->
                query.where.and(and -> and.where.userId().eq(userId).or.userId().isNull().end()))
        .endJoin()
        .build();
  }

  public static IQuery blurTitleOrContentPagingQuery(QuestionPagingDTO paging) {
    return blurTitleOrContentQuery(paging).limit(paging.prefix(), paging.last());
  }

  public static IQuery getQuestionDetailQuery(Integer id, Integer userId) {
    QuestionPagingDTO questionPagingDTO = new QuestionPagingDTO();
    questionPagingDTO.setQuestionId(id);
    questionPagingDTO.setUserId(userId);
    return blurTitleOrContentQuery(questionPagingDTO);
  }
}
